﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using Moq;

namespace MvcWiki.Test.Service.WikiNamespaceService
{
    public class CreateWikiNamespaceFacts
    {
        [Fact]
        public void Call()
        {
            var wikiNamespace = new MvcWiki.Model.WikiNamespace {
                Name = "Namespace",
                Markup = new MvcWiki.Model.WikiMarkup()
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(x => x.CanCreateNamespace()).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            service.CreateWikiNamespace(wikiNamespace);
        }

        [Fact]
        public void Calls_Repository()
        {
            var wikiNamespace = new MvcWiki.Model.WikiNamespace
            {
                Name = "Namespace",
                Markup = new MvcWiki.Model.WikiMarkup()
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();
            wikiNamespaceRepository.Setup(x => x.SaveWikiNamespace(wikiNamespace));

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(x => x.CanCreateNamespace()).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            service.CreateWikiNamespace(wikiNamespace);

            wikiNamespaceRepository.VerifyAll();
        }

        [Fact]
        public void Calls_IUnitOfWork_Commit()
        {
            var wikiNamespace = new MvcWiki.Model.WikiNamespace
            {
                Name = "Namespace",
                Markup = new MvcWiki.Model.WikiMarkup()
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();
            unitOfWork.Setup(x => x.Commit());

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(x => x.CanCreateNamespace()).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            service.CreateWikiNamespace(wikiNamespace);

            unitOfWork.VerifyAll();
        }

        [Fact]
        public void Calls_WikiUserProvider_CanCreateNamespace()
        {
            var wikiNamespace = new MvcWiki.Model.WikiNamespace
            {
                Name = "Namespace",
                Markup = new MvcWiki.Model.WikiMarkup()
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(x => x.CanCreateNamespace()).Returns(true);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            service.CreateWikiNamespace(wikiNamespace);

            wikiUserProvider.Verify(
                x => x.CanCreateNamespace());
        }

        [Fact]
        public void Throws_Exception_If_CanCreateNamespace_Is_False()
        {
            var wikiNamespace = new MvcWiki.Model.WikiNamespace
            {
                Name = "Namespace",
                Markup = new MvcWiki.Model.WikiMarkup()
            };

            var wikiNamespaceRepository = new Mock<MvcWiki.Repository.IWikiNamespaceRepository>();

            var repositoryFactory = new Mock<MvcWiki.Repository.IWikiRepositoryFactory>();
            repositoryFactory.Setup(x => x.GetWikiNamespaceRepository()).Returns(wikiNamespaceRepository.Object);

            var unitOfWork = new Mock<MvcWiki.Repository.IUnitOfWork>();

            var wikiUserProvider = new Mock<MvcWiki.User.IWikiUserProvider>();
            wikiUserProvider.Setup(x => x.CanCreateNamespace()).Returns(false);

            var service = new MvcWiki.Service.WikiNamespaceService(repositoryFactory.Object, unitOfWork.Object, wikiUserProvider.Object);

            Assert.Throws<MvcWiki.Exceptions.AuthorizationException>(
                () => service.CreateWikiNamespace(wikiNamespace));
        }
    }
}
